#include "dev_buzzer.h"

extern int bs_jiffies;
#define RCU_TIMERx                        RCU_TIMER3
#define TIMERx                            TIMER3
#define TIMER_CH_x                        TIMER_CH_0

#define BUZ_PERIOD                        3703
#define BUZ_DUTY                          (BUZ_PERIOD/2)
#define buz_jif                           (bs_jiffies)  

bs_buz_dev_t buzzer;


/*!
    \brief 启动pwm
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void buz_enable()
{
    timer_channel_output_pulse_value_config(TIMERx, TIMER_CH_x, BUZ_DUTY);
    timer_enable(TIMERx);
}


/*!
    \brief 关闭pwm, 控制最后一个脉冲的电平
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void buz_disable()
{
    timer_channel_output_pulse_value_config(TIMERx, TIMER_CH_x, 0);
    timer_event_software_generate(TIMERx, TIMER_EVENT_SRC_UPG);
    timer_disable(TIMERx);
}


/*!
    \brief 设置频率、声音时长、停顿时长
    \param[in]  none
    \param[out] none
    \retval     none
*/
void bs_dev_buz_init()
{
    timer_parameter_struct timer_initpara;
    timer_oc_parameter_struct timer_ocintpara;

    rcu_periph_clock_enable(RCU_TIMERx);

    timer_deinit(TIMERx);

    /* TIMERx configuration */
    timer_initpara.prescaler         = 24-1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = BUZ_PERIOD;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMERx,&timer_initpara);

    /* CH1 configuration in OC TOGGLE mode */
    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
    timer_channel_output_config(TIMERx, TIMER_CH_x, &timer_ocintpara);

    timer_channel_output_pulse_value_config(TIMERx, TIMER_CH_x, 0);
    timer_channel_output_mode_config(TIMERx, TIMER_CH_x, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMERx, TIMER_CH_x, TIMER_OC_SHADOW_DISABLE);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMERx);
    // timer_enable(TIMERx);
    timer_disable(TIMERx);

    buzzer.state = 0;
    buzzer.beep_time = 100;
    buzzer.mute_time = 200;
    buzzer.cycle_count = 0;
}


/*!
    \brief 设置滴声次数
    \param[in]  cmd BEEP_n
    \param[out] none
    \retval     none
*/
void bs_dev_buz_ctl(int cmd)
{
    switch (cmd) {
        case BEEP_0:
            buzzer.state = 0;
            buz_disable();
        break;
        case BEEP_1:
        case BEEP_2:
        case BEEP_3:
        case BEEP_4:
            buzzer.state = 1;
            buzzer.timer = buz_jif+buzzer.beep_time;
            buzzer.cycle_count = cmd;
            buz_enable();
        break;

        default:
            buzzer.state = 0;
            buz_disable();
        break;
    }


}


/*!
    \brief 主程序
    \param[in]  none
    \param[out] none
    \retval     none
*/
void bs_dev_buz_process(void)
{
    switch (buzzer.state) {
        case 0:
        break;

        case 1:
            if (buz_jif > buzzer.timer) {
                buzzer.state = 2;
                buzzer.timer = buz_jif+buzzer.mute_time;
                buz_disable();
                if (buzzer.cycle_count > 0) buzzer.cycle_count--;
                if (buzzer.cycle_count == 0) buzzer.state = 0;
            }
        break;

        case 2:
            if (buz_jif > buzzer.timer) {
                buzzer.state = 1;
                buzzer.timer = buz_jif+buzzer.beep_time;
                buz_enable();
            }
        break;

        default:
        break;
    }
    return;
}
